Micron Document
NexusPi Git Node

Commit fc463eb4c579bbcd7340546e598044bd8345f3a5


Parents : 989d01a
Author : Chad Attermann <attermann@gmail.com>
Date : 2026-06-05T13:01:58-06:00

Improved Provsioning integration and build updates

Changes
Diff

diff --git a/Provisioning.cpp b/Provisioning.cpp
index 72027b5..efe6843 100644
--- a/Provisioning.cpp
+++ b/Provisioning.cpp
@@ -58,6 +58,7 @@ extern uint8_t wifi_mode;
extern char wr_ssid[];
#endif
extern bool kiss_framed_logs;
+extern bool nomadnet_enabled;
// ---------------------------------------------------------------------------
// External hooks into the rest of the firmware.
@@ -97,21 +98,22 @@ static void register_provisioning_namespaces() {
// ----- general namespace -----
auto general = Manager::instance()
.register_namespace("General", PROV_NS_GENERAL)
- .field_bool("kiss_framed_logs", PROV_GENERAL_KISS_LOG, FF_LIVE_APPLY, true,
+ .field_bool("kiss_framed_logs", PROV_GENERAL_KISS_LOG, FF_LIVE_APPLY, kiss_framed_logs,
[](const Value& v) { kiss_framed_logs = v.as_bool(); return true; },
[]() { return kiss_framed_logs; });
#ifdef URTN_STATS_PAGES
general
- .field_bool("enable_nomadnet", PROV_GENERAL_NOMADNET, FF_REBOOT_REQUIRED, true);
+ .field_bool("nomadnet_enabled", PROV_GENERAL_NOMADNET, FF_REBOOT_REQUIRED, nomadnet_enabled,
+ [](const Value& v) { nomadnet_enabled = v.as_bool(); return true; },
+ []() { return nomadnet_enabled; });
#endif
#if defined(LORA_TRANSPORT)
if (lora_interface) {
general
.field_enum(
- "lora_interface_mode", PROV_GENERAL_LORA_MODE, FF_LIVE_APPLY,
- (fint_t)RNS::Type::Interface::MODE_GATEWAY,
+ "lora_interface_mode", PROV_GENERAL_LORA_MODE, FF_LIVE_APPLY, static_cast<fint_t>(lora_interface.mode()),
/* values */ {
RNS::Type::Interface::MODE_GATEWAY,
RNS::Type::Interface::MODE_FULL,
@@ -141,8 +143,7 @@ static void register_provisioning_namespaces() {
if (udp_interface) {
general
.field_enum(
- "udp_interface_mode", PROV_GENERAL_UDP_MODE, FF_LIVE_APPLY,
- (fint_t)RNS::Type::Interface::MODE_GATEWAY,
+ "udp_interface_mode", PROV_GENERAL_UDP_MODE, FF_LIVE_APPLY, static_cast<fint_t>(udp_interface.mode()),
/* values */ {
RNS::Type::Interface::MODE_GATEWAY,
RNS::Type::Interface::MODE_FULL,

diff --git a/RNode_Firmware.ino b/RNode_Firmware.ino
index 12786e5..31eca71 100644
--- a/RNode_Firmware.ino
+++ b/RNode_Firmware.ino
@@ -16,15 +16,17 @@
// CBA Reticulum includes must come before local to avoid collision with local defines
#ifdef HAS_RNS
#include <microReticulum.h>
-#endif
#include "Provisioning.h"
+#if defined(LORA_TRANSPORT)
//#include "LoRaInterface.h"
+#endif
#if defined(UDP_TRANSPORT)
#include "UDPInterface.h"
#endif
#ifdef URTN_STATS_PAGES
#include "Pages.h"
#endif
+#endif // HAS_RNS
#include <Arduino.h>
#include <SPI.h>
@@ -70,6 +72,7 @@ volatile bool serial_buffering = false;
#endif
bool kiss_framed_logs = true;
+bool nomadnet_enabled = true;
#if HAS_CONSOLE
#include "Console.h"
@@ -184,7 +187,6 @@ protected:
// CBA logger callback
void on_log(const char* msg, RNS::LogLevel level) {
if (kiss_framed_logs) {
-Serial.print("[K]");
// Compose "<timestamp> [<level>] <msg>" into a stack buffer to avoid
// String heap allocation. 256 bytes covers the longest practical line.
char line[256];
@@ -197,7 +199,6 @@ Serial.print("[K]");
kiss_indicate_log(line, (size_t)n);
}
else {
-Serial.print("[S]");
// Using individual Serial.print statements to avoid memory allocation for String
Serial.print(RNS::getTimeString());
Serial.print(" [");
@@ -283,7 +284,7 @@ RNS::Interface udp_interface(RNS::Type::NONE);
#elif MCU_VARIANT == MCU_NRF52
#include <microStore/Adapters/InternalFSFileSystem.h>
#include <microStore/Adapters/FlashFSFileSystem.h>
- microStore::FileSystem filesystem;
+ microStore::FileSystem filesystem{microStore::Adapters::InternalFSFileSystem()};
#else
#include <microStore/Adapters/PosixFileSystem.h>
microStore::FileSystem filesystem{microStore::Adapters::PosixFileSystem()};
@@ -325,8 +326,10 @@ void setup() {
// CBA Test
delay(2000);
+#ifdef HAS_RNS
printf("Total SRAM: %7u bytes\n", RNS::Utilities::Memory::heap_size());
printf("Free SRAM: %7u bytes\n", RNS::Utilities::Memory::heap_available());
+#endif
#if defined(ESP32)
printf("Total PSRAM: %7u bytes\n", ESP.getPsramSize());
#endif
@@ -629,24 +632,21 @@ void setup() {
pinMode(SDCARD_MISO, INPUT_PULLUP);
SDSPI.begin(SDCARD_SCLK, SDCARD_MISO, SDCARD_MOSI, SDCARD_CS);
if (!SD.begin(SDCARD_CS, SDSPI)) {
- Serial.println("setupSDCard FAIL");
+ printf("setupSDCard FAIL\n");
} else {
uint32_t cardSize = SD.cardSize() / (1024 * 1024);
- Serial.print("setupSDCard PASS . SIZE = ");
- Serial.print(cardSize / 1024.0);
- Serial.println(" GB");
+ printf("setupSDCard PASS . SIZE = %u GB\n", cardSize / 1024.0);
SD.remove("/logfile");
SD.remove("/logfile.txt");
SD.remove("/tracefile");
SD.remove("/tracedetails");
SD.remove("/tracefile.txt");
SD.remove("/tracedetails.txt");
- Serial.println("DIR: /");
+ printf("DIR: /\n");
File root = SD.open("/");
File file = root.openNextFile();
while(file){
- Serial.print(" FILE: ");
- Serial.println(file.name());
+ printf(" FILE: %s\n", file.name());
file = root.openNextFile();
}
}
@@ -676,7 +676,7 @@ void setup() {
try {
// CBA Init filesystem
HEAD("Initializing filesystem...", RNS::LOG_TRACE);
-#if MCU_VARIANT == MCU_NRF52
+#if BOARD_MODEL == BOARD_RAK4631
// First attempt to initialize RAK15001 flash
TRACE("Looking for RAK15001 flash...");
static const SPIFlash_Device_t device_rak15001 = RAK15001;
@@ -697,6 +697,7 @@ void setup() {
}
#else
filesystem.init();
+ TRACE("Initialized filesystem");
#endif
// Remove legacy files
@@ -734,10 +735,9 @@ void setup() {
filesystem.format();
#endif
#if 1
- Serial.println("Listing filesystem /:");
+ printf("Listing filesystem /:\n");
filesystem.listDirectory("/", [&](const char* path) -> void {
- Serial.print(" ");
- Serial.println(path);
+ printf(" %s\n", path);
});
#endif
#endif // !NDEBUG && RNS_USE_FS
@@ -748,13 +748,24 @@ void setup() {
#if defined(LORA_TRANSPORT)
lora_interface = new LoRaInterface();
+ // Provisioning default
+ lora_interface.mode(RNS::Type::Interface::MODE_GATEWAY);
#endif
#if HAS_WIFI && defined(UDP_TRANSPORT)
if (wifi_mode != WR_WIFI_OFF) {
udp_interface = new UDPInterface();
+ // Provisioning default
+ udp_interface.mode(RNS::Type::Interface::MODE_GATEWAY);
}
#endif
+ // Provisioning default
+ reticulum.transport_enabled(true);
+ // Provisioning default
+ reticulum.probe_destination_enabled(true);
+ // Provisioning default
+ reticulum.remote_management_enabled(true);
+
#ifdef HAS_PROVISIONING
// Bring the Provisioning subsystem up. Loads persisted MsgPack files
// (including the radio + general namespaces registered here) and fires
@@ -762,6 +773,7 @@ void setup() {
// disk value differs from the declared default — so on a fresh device
// the lora_* globals stay at their Config.h defaults until either
// eeprom_conf_load() runs or a Provisioning SetState arrives.
+ // CBA NOTE: All app-default-values must be set *before* calling init_provisioning so that they take effect for fresh installs
HEAD("Initializing Provisioning subsystem...", RNS::LOG_TRACE);
init_provisioning();
auto& prov = RNS::Provisioning::Manager::instance();
@@ -778,16 +790,12 @@ void setup() {
#if defined(LORA_TRANSPORT)
HEAD("Registering LoRA Interface...", RNS::LOG_TRACE);
- // Provisioning
- //lora_interface.mode(RNS::Type::Interface::MODE_GATEWAY);
RNS::Transport::register_interface(lora_interface);
TRACEF("LoRaInterface hash: %s", lora_interface.get_hash().toHex().c_str());
#endif
#if HAS_WIFI && defined(UDP_TRANSPORT)
if (wifi_mode != WR_WIFI_OFF) {
HEAD("Registering UDP Interface...", RNS::LOG_TRACE);
- // Provisioning
- //udp_interface.mode(RNS::Type::Interface::MODE_GATEWAY);
RNS::Transport::register_interface(udp_interface);
TRACEF("UDPInterface hash: %s", udp_interface.get_hash().toHex().c_str());
}
@@ -795,10 +803,8 @@ void setup() {
HEAD("Creating Reticulum instance...", RNS::LOG_TRACE);
reticulum = RNS::Reticulum();
- // Provisioning
- //reticulum.transport_enabled(op_mode == MODE_TNC);
- // Provisioning
- //reticulum.probe_destination_enabled(true);
+ // CBA NOTE: `transport_enabled` needs to always be overridden to false when op_mode is not MODE_TNC
+ if (op_mode != MODE_TNC) reticulum.transport_enabled(false);
reticulum.start();
// Set loop callback only after the Reticulum instance is started
@@ -825,7 +831,7 @@ void setup() {
RNS::Destination destination(RNS::Transport::identity(), RNS::Type::Destination::IN, RNS::Type::Destination::SINGLE, "rnstransport", "local");
#ifdef URTN_STATS_PAGES
- if (prov.field(PROV_NS_GENERAL, PROV_GENERAL_NOMADNET).as_bool()) {
+ if (nomadnet_enabled) {
// Create an IN/SINGLE destination on the NomadNet aspect, so
// clients (this example, or a Python NomadNet browser) can find
// us by aspect/announce and open a Link.

diff --git a/boards/lilygo_t_echo.json b/boards/lilygo_t_echo.json
new file mode 100644
index 0000000..aa0601e
--- /dev/null
+++ b/boards/lilygo_t_echo.json
@@ -0,0 +1,73 @@
+{
+ "build": {
+ "arduino": {
+ "ldscript": "nrf52840_s140_v6.ld"
+ },
+ "core": "nRF5",
+ "cpu": "cortex-m4",
+ "extra_flags": "-DARDUINO_NRF52840_TTGO_EINK -DNRF52840_XXAA",
+ "f_cpu": "64000000L",
+ "hwids": [
+ [
+ "0x239A",
+ "0x4405"
+ ],
+ [
+ "0x239A",
+ "0x0029"
+ ],
+ [
+ "0x239A",
+ "0x002A"
+ ]
+ ],
+ "usb_product": "LilyGo T-Echo",
+ "mcu": "nrf52840",
+ "variant": "lilygo_t_echo",
+ "variants_dir": "variants",
+ "bsp": {
+ "name": "adafruit"
+ },
+ "softdevice": {
+ "sd_flags": "-DS140",
+ "sd_name": "s140",
+ "sd_version": "6.1.1",
+ "sd_fwid": "0x00B6"
+ },
+ "bootloader": {
+ "settings_addr": "0xFF000"
+ }
+ },
+ "connectivity": [
+ "bluetooth"
+ ],
+ "debug": {
+ "jlink_device": "nRF52840_xxAA",
+ "onboard_tools": [
+ "jlink"
+ ],
+ "openocd_target": "nrf52840-mdk-rs",
+ "svd_path": "nrf52840.svd"
+ },
+ "frameworks": [
+ "arduino"
+ ],
+ "name": "LilyGo T-Echo (Adafruit BSP)",
+ "upload": {
+ "maximum_ram_size": 248832,
+ "maximum_size": 815104,
+ "speed": 115200,
+ "protocol": "nrfutil",
+ "protocols": [
+ "jlink",
+ "nrfjprog",
+ "nrfutil",
+ "stlink"
+ ],
+ "use_1200bps_touch": true,
+ "require_upload_port": true,
+ "wait_for_upload_port": true
+ },
+ "url": "https://lilygo.cc/products/t-echo-lilygo",
+ "vendor": "LILYGO"
+}

diff --git a/extra_script.py b/extra_script.py
index 1904d06..d9c3dad 100644
--- a/extra_script.py
+++ b/extra_script.py
@@ -44,7 +44,7 @@ def post_upload(source, target, env):
# firmware pacakaging is incomplete due to missing console image
#firmware_package(env)
elif ("nordicnrf52" in platform):
- time.sleep(5)
+ time.sleep(10)
# device provisioning is incomplete and only currently appropriate for 915MHz RAK4631
device_provision(env)
time.sleep(5)
@@ -93,6 +93,8 @@ def device_provision(env):
env.Execute("rnodeconf --product c3 --model c8 --hwrev 1 --rom " + env.subst("$UPLOAD_PORT"))
case "rak4631" | "rak4631_local":
env.Execute("rnodeconf --product 10 --model 12 --hwrev 1 --rom " + env.subst("$UPLOAD_PORT"))
+ case "techo" | "techo_local":
+ env.Execute("rnodeconf --product 15 --model 17 --hwrev 1 --rom " + env.subst("$UPLOAD_PORT"))
case "heltec_t114" | "heltec_t114_local":
env.Execute("rnodeconf --product c2 --model c7 --hwrev 1 --rom " + env.subst("$UPLOAD_PORT"))
case _:

diff --git a/platformio.ini b/platformio.ini
index 82a9251..866533b 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -9,6 +9,31 @@
; https://docs.platformio.org/page/projectconf.html
[platformio]
+default_envs =
+ rnode-ng-20
+ rnode-ng-21
+ ttgo-t-beam
+ ttgo-t-beam-sx1262
+ ttgo-t-beam-supreme
+ lilygo-t3-s3
+ lilygo-t3-s3-sx127x
+ lilygo-t3-s3-sx1280-pa
+ lilygo-t-deck
+ ttgo-lora32-v1
+ ttgo-lora32-v2
+ ttgo-lora32-v2-extled
+ ttgo-lora32-v21
+ ttgo-lora32-v21-extled
+ ttgo-lora32-v21-tcxo
+ heltec_wifi_lora_32_V2
+ heltec_wifi_lora_32_V2-extled
+ heltec_wifi_lora_32_V3
+ heltec_wifi_lora_32_V4
+ featheresp32
+ seeed_xiao_esp32s3
+ generic-esp32
+ wiscore_rak4631
+ lilygo-t-echo
; Change source and include directories to root of project since RNode places them here
include_dir = .
src_dir = .
@@ -40,6 +65,7 @@ build_flags =
; removes it via build_unflags so the macOS dev binary launches with
; no Reticulum interfaces (UDPInterface can be added later).
-DLORA_TRANSPORT
+ -DRNS_LOW_MEMORY_REBOOT
-DRNS_DEBUG_HEAP
-DRNS_DEBUG_MEMORY
-DRNS_DEBUG_METRICS
@@ -328,7 +354,6 @@ build_flags =
-DARDUINO_USB_CDC_ON_BOOT=1
; Enable UARDUINO_USB_CDC_ON_BOOT will turn off printing and will not block when using the battery
; -UARDUINO_USB_CDC_ON_BOOT
- -DBOARD_HAS_PSRAM=1
-DRNS_CONTAINER_ALLOCATOR=RNS_PSRAM_ALLOCATOR
-DUSTORE_USE_POSIXFS=1
-DURTN_PATH_TABLE_MAX_RECS=2000
@@ -568,13 +593,14 @@ extends = env:embedded
platform = espressif32
board = heltec_wifi_lora_32_V3
custom_variant = heltec32v3
-board_build.partitions = no_ota.csv
+;board_build.partitions = no_ota.csv
+board_upload.flash_size = 8MB
+board_upload.maximum_size = 8388608
+board_build.partitions = default_8MB.csv
board_build.filesystem = littlefs
build_flags =
${env:embedded.build_flags}
-DBOARD_MODEL=BOARD_HELTEC32_V3
- ; CBA BOARD_HAS_PSRAM=1 causes malloc to automatically use PSRAM
- ;-DBOARD_HAS_PSRAM=1
-DUSTORE_USE_POSIXFS=1
-DURTN_PATH_TABLE_MAX_RECS=500
-DRNS_PATH_TABLE_SEGMENT_SIZE=24576 ; 24 KB
@@ -598,15 +624,18 @@ extends = env:embedded
platform = espressif32
board = esp32-s3-devkitc-1
custom_variant = heltec32v4pa
-board_build.partitions = no_ota.csv
+;board_build.partitions = no_ota.csv
+board_upload.flash_size = 16MB
+board_upload.maximum_size = 16777216
+board_build.partitions = default_16MB.csv
board_build.filesystem = littlefs
+board_build.psram = enabled
build_flags =
${env:embedded.build_flags}
-DBOARD_MODEL=BOARD_HELTEC32_V4
- ; CBA BOARD_HAS_PSRAM=1 causes malloc to automatically use PSRAM
- ;-DBOARD_HAS_PSRAM=1
-DARDUINO_USB_CDC_ON_BOOT=1
-DBOARD_HAS_PSRAM=1
+ -DUDP_TRANSPORT
-DRNS_CONTAINER_ALLOCATOR=RNS_PSRAM_ALLOCATOR
-DUSTORE_USE_POSIXFS=1
-DURTN_PATH_TABLE_MAX_RECS=2000
@@ -737,13 +766,61 @@ lib_deps =
adafruit/SdFat - Adafruit Fork
https://github.com/attermann/Adafruit_SPIFlash#littlefs
+; MCU: Nordic nRF52840 (32-bit ARM Cortex-M4, 64 MHz)
+; SRAM: 256 KB
+; PSRAM: N/A
+; Flash: 1 MB internal
+; External Flash Interface: N/A
+; LoRa: Semtech SX1262
+; NOTE: Must double-click RESET button (top-left) to enter DFU mode before uploading firmware
+[env:lilygo-t-echo]
+extends = env:embedded
+platform = nordicnrf52
+board = nrf52840_dk_adafruit
+custom_variant = techo
+board_build.partitions = no_ota.csv
+board_build.filesystem = littlefs
+; Required so the linker pulls in Adafruit_TinyUSB_API.cpp's strong definition
+; of TinyUSB_Device_Init() — declared weak in the BSP header, so without this
+; the BSP's call to it from loop_task() gets patched to a no-op and USB CDC
+; never initializes.
+lib_archive = no
+build_unflags =
+ ${env:embedded.build_unflags}
+ -fno-exceptions ; Required for exception handling on nordicnrf52
+ -fno-rtti ; Required for exception handling on nordicnrf52
+ --specs=nano.specs ; Required for exception handling on nordicnrf52
+ -DHAS_PROVISIONING ; nRF52 flash too tight to include Provisioning
+build_flags =
+ ${env:embedded.build_flags}
+ -fexceptions ; Required for exception handling on nordicnrf52
+ -frtti ; Required for exception handling on nordicnrf52
+ --specs=nosys.specs ; Required for exception handling on nordicnrf52
+ -DBOARD_MODEL=BOARD_TECHO
+ ; CBA The heap pool allocator is what was causing the board to fail to boot due to very early static init failure
+ -DRNS_DEFAULT_ALLOCATOR=RNS_HEAP_POOL_ALLOCATOR
+ ;-DRNS_HEAP_POOL_BUFFER_SIZE=131072
+ -DRNS_HEAP_POOL_BUFFER_SIZE=98304
+ -DUSTORE_USE_INTERNALFS
+ -DURTN_PATH_TABLE_MAX_RECS=25
+ -DRNS_PATH_TABLE_SEGMENT_SIZE=2048 ; 2 KB
+ -DRNS_PATH_TABLE_SEGMENT_COUNT=6
+lib_deps =
+ ${env:embedded.lib_deps}
+ https://github.com/liamcottle/esp8266-oled-ssd1306#e16cee124fe26490cb14880c679321ad8ac89c95
+ adafruit/Adafruit NeoPixel@^1.12.0
+ zinggjm/GxEPD2
+ https://github.com/attermann/microStore.git
+ https://github.com/attermann/microReticulum.git
+upload_protocol = nrfutil
+upload_port = /dev/cu.usbmodem101
+
[env:ttgo-t-beam-local]
extends = env:embedded
platform = espressif32
board = ttgo-t-beam
-upload_speed = 460800
custom_variant = tbeam_local
board_build.partitions = no_ota.csv
board_build.filesystem = littlefs
@@ -761,12 +838,12 @@ lib_deps =
microStore=symlink://../microStore
microReticulum=symlink://../microReticulum
monitor_filters = esp32_exception_decoder
+upload_speed = 460800
[env:ttgo-lora32-v21-local]
extends = env:embedded
platform = espressif32
board = ttgo-lora32-v21
-upload_speed = 460800
custom_variant = lora32v21_local
board_build.partitions = no_ota.csv
board_build.filesystem = littlefs
@@ -786,12 +863,12 @@ lib_deps =
microStore=symlink://../microStore
microReticulum=symlink://../microReticulum
monitor_filters = esp32_exception_decoder
+upload_speed = 460800
[env:ttgo-lora32-v21-sd-local]
extends = env:embedded
platform = espressif32
board = ttgo-lora32-v21
-upload_speed = 460800
custom_variant = lora32v21_local
board_build.partitions = no_ota.csv
board_build.filesystem = littlefs
@@ -817,6 +894,7 @@ lib_deps =
microStore=symlink://../microStore
microReticulum=symlink://../microReticulum
monitor_filters = esp32_exception_decoder
+upload_speed = 460800
; also Heltec Wireless Tracker
[env:heltec_wifi_lora_32_V4-local]
@@ -824,7 +902,10 @@ extends = env:embedded
platform = espressif32
board = esp32-s3-devkitc-1
custom_variant = heltec32v4pa_local
-board_build.partitions = no_ota.csv
+;board_build.partitions = no_ota.csv
+board_upload.flash_size = 16MB
+board_upload.maximum_size = 16777216
+board_build.partitions = default_16MB.csv
board_build.filesystem = littlefs
build_flags =
${env:embedded.build_flags}
@@ -854,10 +935,12 @@ platform = espressif32
;board = heltec_wifi_lora_32_V3
board = esp32-s3-devkitc-1
custom_variant = heltec32v4pa_local
+;board_build.partitions = no_ota.csv
board_upload.flash_size = 16MB
-board_build.psram = enabled
-board_build.partitions = no_ota.csv
+board_upload.maximum_size = 16777216
+board_build.partitions = default_16MB.csv
board_build.filesystem = littlefs
+board_build.psram = enabled
build_flags =
${env:embedded.build_flags}
-DBOARD_MODEL=BOARD_HELTEC32_V4
@@ -902,9 +985,12 @@ board = esp32-s3-devkitc-1
;board_build.variants_dir = variants
;board_build.variant = heltec_V4
custom_variant = heltec32v4pa_local
+;board_build.partitions = no_ota.csv
board_upload.flash_size = 16MB
-board_build.partitions = no_ota.csv
+board_upload.maximum_size = 16777216
+board_build.partitions = default_16MB.csv
board_build.filesystem = littlefs
+board_build.psram = enabled
build_flags =
${env:embedded.build_flags}
-DBOARD_MODEL=BOARD_HELTEC32_V4
@@ -944,9 +1030,11 @@ extends = env:embedded
platform = nordicnrf52
board = rak4630
custom_variant = rak4631_local
+board_build.variants_dir = variants
+board_build.variant = rak4630
board_build.partitions = no_ota.csv
board_build.filesystem = littlefs
-build_src_filter = ${env:embedded.build_src_filter} +<variants/rak4630>
+;build_src_filter = ${env:embedded.build_src_filter} +<variants/rak4630>
build_unflags =
${env:embedded.build_unflags}
-fno-exceptions ; Required for exception handling on nordicnrf52
@@ -959,7 +1047,7 @@ build_flags =
-frtti ; Required for exception handling on nordicnrf52
--specs=nosys.specs ; Required for exception handling on nordicnrf52
;-Wl,-Map,output.map
- -I variants/rak4630
+ ;-I variants/rak4630
-DBOARD_MODEL=BOARD_RAK4631
; CBA TEST
;-DRNS_DEFAULT_ALLOCATOR=RNS_HEAP_ALLOCATOR
@@ -988,15 +1076,19 @@ lib_deps =
; Flash: 1 MB internal
; External Flash Interface: N/A
; LoRa: Semtech SX1262
-[env:heltec_t114_local]
+; NOTE: Must double-click RESET button (top-left) to enter DFU mode before uploading firmware
+[env:lilygo-t-echo-local]
extends = env:embedded
-;upload_port = /dev/cu.usbmodem1101
platform = nordicnrf52
-;board = nrf52840_dk_adafruit
-board = nrf52840_dk
-custom_variant = heltec_t114_local
+board = nrf52840_dk_adafruit
+custom_variant = techo_local
board_build.partitions = no_ota.csv
board_build.filesystem = littlefs
+; Required so the linker pulls in Adafruit_TinyUSB_API.cpp's strong definition
+; of TinyUSB_Device_Init() — declared weak in the BSP header, so without this
+; the BSP's call to it from loop_task() gets patched to a no-op and USB CDC
+; never initializes.
+lib_archive = no
build_unflags =
${env:embedded.build_unflags}
-fno-exceptions ; Required for exception handling on nordicnrf52
@@ -1008,10 +1100,11 @@ build_flags =
-fexceptions ; Required for exception handling on nordicnrf52
-frtti ; Required for exception handling on nordicnrf52
--specs=nosys.specs ; Required for exception handling on nordicnrf52
- -DBOARD_MODEL=BOARD_HELTEC_T114
- ; CBA TEST
+ -DBOARD_MODEL=BOARD_TECHO
+ ; CBA The heap pool allocator is what was causing the board to fail to boot due to very early static init failure
-DRNS_DEFAULT_ALLOCATOR=RNS_HEAP_POOL_ALLOCATOR
- -DRNS_HEAP_POOL_BUFFER_SIZE=204800
+ ;-DRNS_HEAP_POOL_BUFFER_SIZE=131072
+ -DRNS_HEAP_POOL_BUFFER_SIZE=98304
-DUSTORE_USE_INTERNALFS
-DURTN_PATH_TABLE_MAX_RECS=25
-DRNS_PATH_TABLE_SEGMENT_SIZE=2048 ; 2 KB
@@ -1020,8 +1113,12 @@ lib_deps =
${env:embedded.lib_deps}
https://github.com/liamcottle/esp8266-oled-ssd1306#e16cee124fe26490cb14880c679321ad8ac89c95
adafruit/Adafruit NeoPixel@^1.12.0
+ zinggjm/GxEPD2@^1.6.9
microStore=symlink://../microStore
microReticulum=symlink://../microReticulum
+upload_protocol = nrfutil
+upload_port = /dev/cu.usbmodem101
+upload_speed = 460800
; MCU: Nordic nRF52840 (32-bit ARM Cortex-M4, 64 MHz)
; SRAM: 256 KB
@@ -1029,12 +1126,13 @@ lib_deps =
; Flash: 1 MB internal
; External Flash Interface: N/A
; LoRa: Semtech SX1262
-[env:lilygo-techo]
+[env:heltec_t114-local]
extends = env:embedded
;upload_port = /dev/cu.usbmodem1101
platform = nordicnrf52
-board = nrf52840_dk_adafruit
-custom_variant = techo_local
+;board = nrf52840_dk_adafruit
+board = nrf52840_dk
+custom_variant = heltec_t114_local
board_build.partitions = no_ota.csv
board_build.filesystem = littlefs
build_unflags =
@@ -1048,7 +1146,7 @@ build_flags =
-fexceptions ; Required for exception handling on nordicnrf52
-frtti ; Required for exception handling on nordicnrf52
--specs=nosys.specs ; Required for exception handling on nordicnrf52
- -DBOARD_MODEL=BOARD_TECHO
+ -DBOARD_MODEL=BOARD_HELTEC_T114
; CBA TEST
-DRNS_DEFAULT_ALLOCATOR=RNS_HEAP_POOL_ALLOCATOR
-DRNS_HEAP_POOL_BUFFER_SIZE=204800

diff --git a/variants/lilygo_t_echo/WVariant.h b/variants/lilygo_t_echo/WVariant.h
new file mode 100644
index 0000000..500fc6b
--- /dev/null
+++ b/variants/lilygo_t_echo/WVariant.h
@@ -0,0 +1,36 @@
+/*
+ Copyright (c) 2015 Arduino LLC. All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <nrf.h>
+#include <nrf_soc.h>
+#include <nrf_sdm.h>
+#include <nrf_gpio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const uint32_t g_ADigitalPinMap[] ;
+
+#ifdef __cplusplus
+} // extern "C"
+#endif

diff --git a/variants/lilygo_t_echo/variant.cpp b/variants/lilygo_t_echo/variant.cpp
new file mode 100644
index 0000000..ac7cb35
--- /dev/null
+++ b/variants/lilygo_t_echo/variant.cpp
@@ -0,0 +1,53 @@
+/*
+ Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+ Copyright (c) 2016 Sandeep Mistry All right reserved.
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "variant.h"
+#include "nrf.h"
+#include "wiring_constants.h"
+#include "wiring_digital.h"
+
+const uint32_t g_ADigitalPinMap[] = {
+ // P0 - pins 0 and 1 are hardwired for xtal and should never be enabled
+ 0xff, 0xff, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+
+ // P1
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
+
+void initVariant()
+{
+ pinMode(PIN_LED1, OUTPUT);
+ ledOff(PIN_LED1);
+
+ pinMode(PIN_LED2, OUTPUT);
+ ledOff(PIN_LED2);
+
+ pinMode(PIN_LED3, OUTPUT);
+ ledOff(PIN_LED3);
+}
+
+void variant_shutdown()
+{
+ // To power off the T-Echo, the display must be set
+ // as an input pin; otherwise, there will be leakage current.
+ pinMode(PIN_EINK_CS, INPUT);
+ pinMode(PIN_EINK_DC, INPUT);
+ pinMode(PIN_EINK_RES, INPUT);
+ pinMode(PIN_EINK_BUSY, INPUT);
+}

diff --git a/variants/lilygo_t_echo/variant.h b/variants/lilygo_t_echo/variant.h
new file mode 100644
index 0000000..7d802da
--- /dev/null
+++ b/variants/lilygo_t_echo/variant.h
@@ -0,0 +1,231 @@
+/*
+ Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+ Copyright (c) 2016 Sandeep Mistry All right reserved.
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef _VARIANT_LILYGO_T_ECHO_
+#define _VARIANT_LILYGO_T_ECHO_
+
+/** Master clock frequency */
+#define VARIANT_MCK (64000000ul)
+
+#define USE_LFXO // Board uses 32khz crystal for LF
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#define TTGO_T_ECHO
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT (48)
+#define NUM_DIGITAL_PINS (48)
+#define NUM_ANALOG_INPUTS (1)
+#define NUM_ANALOG_OUTPUTS (0)
+
+// LEDs
+#define PIN_LED1 (0 + 14) // 13 red (confirmed on 1.0 board)
+// Unused(by firmware) LEDs:
+#define PIN_LED2 (0 + 15) // 14 blue
+#define PIN_LED3 (0 + 13) // 15 green
+
+#define LED_RED PIN_LED3
+#define LED_BLUE PIN_LED1
+#define LED_GREEN PIN_LED2
+
+#define LED_STATE_ON 0 // State when LED is lit
+
+/*
+ * Buttons
+ */
+#define PIN_BUTTON1 (32 + 10)
+#define BUTTON_ACTIVE_LOW true
+#define BUTTON_ACTIVE_PULLUP true
+#define PIN_BUTTON2 (0 + 18) // 0.18 is labeled on the board as RESET but we configure it in the bootloader as a regular GPIO
+#define PIN_BUTTON_TOUCH (0 + 11) // 0.11 is the soft touch button on T-Echo
+#define BUTTON_TOUCH_ACTIVE_LOW true
+#define BUTTON_TOUCH_ACTIVE_PULLUP true
+
+#define BUTTON_CLICK_MS 400
+#define BUTTON_TOUCH_MS 200
+
+/*
+ * Analog pins
+ */
+#define PIN_A0 (4) // Battery ADC
+
+#define BATTERY_PIN PIN_A0
+
+static const uint8_t A0 = PIN_A0;
+
+#define ADC_RESOLUTION 14
+
+#define PIN_NFC1 (9)
+#define PIN_NFC2 (10)
+
+/*
+ * Serial interfaces
+ */
+#define SERIAL_PRINT_PORT 0
+
+/*
+No longer populated on PCB
+*/
+// #define PIN_SERIAL2_RX (0 + 6)
+// #define PIN_SERIAL2_TX (0 + 8)
+// #define PIN_SERIAL2_EN (0 + 17)
+
+/**
+ Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA (26)
+#define PIN_WIRE_SCL (27)
+
+/* touch sensor, active high */
+
+#define TP_SER_IO (0 + 11)
+
+/*
+External serial flash WP25R1635FZUIL0
+*/
+
+// QSPI Pins
+#define PIN_QSPI_SCK (32 + 14)
+#define PIN_QSPI_CS (32 + 15)
+#define PIN_QSPI_IO0 (32 + 12) // MOSI if using two bit interface
+#define PIN_QSPI_IO1 (32 + 13) // MISO if using two bit interface
+#define PIN_QSPI_IO2 (0 + 7) // WP if using two bit interface (i.e. not used)
+#define PIN_QSPI_IO3 (0 + 5) // HOLD if using two bit interface (i.e. not used)
+
+// On-board QSPI Flash
+#define EXTERNAL_FLASH_DEVICES MX25R1635F
+#define EXTERNAL_FLASH_USE_QSPI
+
+/*
+ * Lora radio
+ */
+
+#define USE_SX1262
+#define USE_SX1268
+#define SX126X_CS (0 + 24) // FIXME - we really should define LORA_CS instead
+#define SX126X_DIO1 (0 + 20)
+// Note DIO2 is attached internally to the module to an analog switch for TX/RX switching
+#define SX1262_DIO3 \
+ (0 + 21) // This is used as an *output* from the sx1262 and connected internally to power the tcxo, do not drive from the main
+// CPU?
+#define SX126X_BUSY (0 + 17)
+#define SX126X_RESET (0 + 25)
+// Not really an E22 but TTGO seems to be trying to clone that
+#define SX126X_DIO2_AS_RF_SWITCH
+#define SX126X_DIO3_TCXO_VOLTAGE 1.8
+#define TCXO_OPTIONAL
+// Internally the TTGO module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for the sx1262interface
+// code)
+
+// #define LORA_DISABLE_SENDING // Define this to disable transmission for testing (power testing etc...)
+
+// #undef SX126X_CS
+
+/*
+ * eink display pins
+ */
+
+#define PIN_EINK_EN (32 + 11) // Note: this is really just backlight power
+#define PIN_EINK_CS (0 + 30)
+#define PIN_EINK_BUSY (0 + 3)
+#define PIN_EINK_DC (0 + 28)
+#define PIN_EINK_RES (0 + 2)
+#define PIN_EINK_SCLK (0 + 31)
+#define PIN_EINK_MOSI (0 + 29) // also called SDI
+
+// Controls power for all peripherals (eink + GPS + LoRa + Sensor)
+#define PIN_POWER_EN (0 + 12)
+
+#define PIN_SPI1_MISO \
+ (32 + 7) // FIXME not really needed, but for now the SPI code requires something to be defined, pick an used GPIO
+#define PIN_SPI1_MOSI PIN_EINK_MOSI
+#define PIN_SPI1_SCK PIN_EINK_SCLK
+
+/*
+ * GPS pins
+ */
+
+#define GPS_L76K
+#define PIN_GPS_REINIT (32 + 5) // An output to reset L76K GPS. As per datasheet, low for > 100ms will reset the L76K
+
+#define PIN_GPS_STANDBY (32 + 2) // An output to wake GPS, low means allow sleep, high means force wake
+// Seems to be missing on this new board
+#define PIN_GPS_PPS (32 + 4) // Pulse per second input from the GPS
+#define GPS_TX_PIN (32 + 8) // This is for bits going TOWARDS the CPU
+#define GPS_RX_PIN (32 + 9) // This is for bits going TOWARDS the GPS
+
+#define GPS_THREAD_INTERVAL 50
+
+#define PIN_SERIAL1_RX GPS_RX_PIN
+#define PIN_SERIAL1_TX GPS_TX_PIN
+
+// PCF8563 RTC Module
+#define PIN_RTC_INT (0 + 16) // Interrupt from the PCF8563 RTC
+#define PCF8563_RTC 0x51
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 2
+
+// For LORA, spi 0
+#define PIN_SPI_MISO (0 + 23)
+#define PIN_SPI_MOSI (0 + 22)
+#define PIN_SPI_SCK (0 + 19)
+
+static const uint8_t SS = SX126X_CS;
+static const uint8_t MOSI = PIN_SPI_MOSI;
+static const uint8_t MISO = PIN_SPI_MISO;
+static const uint8_t SCK = PIN_SPI_SCK;
+
+// To debug via the segger JLINK console rather than the CDC-ACM serial device
+// #define USE_SEGGER
+
+// Battery
+// The battery sense is hooked to pin A0 (4)
+// it is defined in the anlaolgue pin section of this file
+// and has 12 bit resolution
+#define BATTERY_SENSE_RESOLUTION_BITS 12
+#define BATTERY_SENSE_RESOLUTION 4096.0
+#undef AREF_VOLTAGE
+#define AREF_VOLTAGE 3.0
+#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
+#define ADC_MULTIPLIER (2.0F)
+
+// #define NO_EXT_GPIO 1
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ * Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#endif

Served by rngit 1.5.2 - Generated in 0.03s